﻿
namespace HSS.Xaml.UI.Media.Animation
{
	#region Using Directives
	using System;
	using System.Windows;
	using System.Windows.Media.Animation;
	#endregion

	#region FrameworkElementEffect
	/// <summary>
	/// Provides a programmatic effect on a FrameworkElement.
	/// </summary>
	public abstract class FrameworkElementEffect
	{
		#region Events
		/// <summary>
		/// Occurs when the storyboard completes.
		/// </summary>
		public event EventHandler Completed;
		#endregion

		#region Fields
		Storyboard _storyboard;
		string _targetKey;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructor
		/// </summary>
		protected FrameworkElementEffect()
		{
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets the Target FrameworkElement.
		/// </summary>
		public FrameworkElement Target
		{
			get { return _target; }
		} FrameworkElement _target;
		#endregion

		#region Abstract Methods
		/// <summary>
		/// Creates the desired StoryBoard.
		/// </summary>
		/// <param name="target">The FrameworkElement that will recieve the effect.</param>
		/// <returns>The created Storyboard.</returns>
		protected abstract Storyboard CreateStoryboard(FrameworkElement target);
		#endregion

		#region Methods
		/// <summary>
		/// Attach the storyboard to the target FrameworkElement.
		/// </summary>
		protected virtual void Attach()
		{
			this._storyboard = this.CreateStoryboard(this._target);
			this._storyboard.Completed += new EventHandler(this.OnCompleted);
			this._target.Resources.Add(_targetKey, _storyboard);
		}
		/// <summary>
		/// Detach the storyboard from the target FrameworkElement.
		/// </summary>
		protected virtual void Detach()
		{
			if (this._target != null)
			{
				this._target.Resources.Remove(this._targetKey);
				this._target = null;
			}
			if (_storyboard != null)
				_storyboard = null;
		}
		/// <summary>
		/// Begins the animation effect.
		/// </summary>
		/// <param name="targetKey">The key to reference the storyboard in the target's resource collection.</param>
		/// <param name="target">The FrameworkElement to animate.</param>
		public virtual void Start(string targetKey, FrameworkElement target)
		{
			this._targetKey = targetKey;
			this._target = target;
			this.Attach();
			this._storyboard.Begin();
		}
		/// <summary>
		/// Ends the animation effect.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Stop")]
		public virtual void Stop()
		{
			if (null != this._storyboard)
				this._storyboard.Stop();
			this.Detach();
		}
		/// <summary>
		/// Fires the Completed event when the storyboard completes.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">An System.EventArgs that contains no event data.</param>
		protected virtual void OnCompleted(object sender, EventArgs e)
		{
			var handler = this.Completed;
			if (null != handler)
				handler(sender, e);
			this.Detach();
		}
		#endregion
	}
	#endregion
}
